home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / devel / lang / lisp / stk-3.002 / stk-3 / STk-3.1 / Demos / hanoi.stk < prev    next >
Encoding:
Text File  |  1996-02-22  |  6.7 KB  |  268 lines

  1. #!/usr/local/bin/stk -f
  2. ;;
  3. ;; Hanoi - Towers of Hanoi diversion
  4. ;;
  5. ;; This program is a rewriting in STk of a program found on the net. Original
  6. ;; author is Damon A Permezel (probably fubar!dap@natinst.com)
  7. ;; Re-writing is very direct and needs much more working
  8. ;;
  9.  
  10. (define *gc-verbose*    #f)
  11.  
  12. (define hanoi-canvas    "")
  13. (define hanoi-running     #f)
  14. (define hanoi-stop    #f)
  15. (define previousRings   0)
  16. (define max-rings     20)
  17. (define num-rings    6)
  18. (define colours        '(DarkOliveGreen snow4 royalblue2 palegreen4
  19.               rosybrown1 wheat4 tan2 brown2 tomato3 hotpink3))
  20.  
  21. (define pole        (make-vector 3))         ; elts are <nRing . xPos>
  22. (define ring         (make-vector (+ max-rings 1))); elts are <pole width . obj>
  23.  
  24. (define accel        0)
  25. (define base        32)
  26. (define fly-row     32)
  27. (define width-incr    12)
  28. (define width-min    (* 8 width-incr))    
  29. (define ring-height     26)
  30. (define ring-spacing    (* 2 (/ ring-height 3)))
  31.  
  32.  
  33. ;;
  34. ;; Setup the main window
  35. ;;
  36. (define (SetupHanoi)
  37.   (wm 'title "." "Towers of Hanoi")
  38.  
  39.   ;;
  40.   ;; setup frame and main menu button
  41.   ;;
  42.   (label ".title" :text "Towers of Hanoi" :bd 4 :fg "RoyalBlue" :relief "ridge")
  43.   (frame ".f")
  44.   (button ".f.run"  :text "Run"  :command (lambda ()
  45.                         (DoHanoi (.nrframe.scale 'get) #t)))
  46.   (button ".f.stop" :text "Stop" :command (lambda ()
  47.                         (set! hanoi-stop 1)))
  48.   (button ".f.quit" :text "Quit" :command (lambda ()
  49.                         (exit 0)))
  50.   (pack .f.run .f.stop .f.quit :fill "x" :side "left" :expand #t)
  51.  
  52.   ;;
  53.   ;; setup next frame, for #rings slider
  54.   ;;
  55.   (frame ".nrframe" :bd 2 :relief 'raised)
  56.   (pack [label ".nrframe.label" :text "Number of Rings: " :width 15 :anchor 'e]
  57.     :side "left")
  58.   (pack [scale ".nrframe.scale" :orient 'hor :from 1 :to max-rings :font "fixed"
  59.                     :command (lambda (val)
  60.                        (set! num-rings val))]
  61.     :side "right" :expand #t :fill "x")
  62.   (.nrframe.scale 'set num-rings)
  63.  
  64.   ;;
  65.   ;; setup next frame, for speed slider
  66.   ;;
  67.   (frame ".speed-frame" :bd 2 :relief 'raised)
  68.   (pack [label ".speed-frame.label" :text "Speed: " :width 15 :anchor 'e]
  69.     :side "left")
  70.   (pack [scale ".speed-frame.scale" :orient 'hor :from 1 :to 100 :font "fixed"
  71.                           :command (lambda (val)
  72.                      (set! accel val))]
  73.     :side "right" :expand #t :fill "x")    
  74.   (.speed-frame.scale 'set 100)
  75.  
  76.   ;;
  77.   ;; setup frame for canvas to appear in
  78.   ;;
  79.   (frame ".canv-frame" :bd 4 :relief 'groove)
  80.   (pack [canvas ".canv-frame.canvas" :relief 'sunken])
  81.   (set! hanoi-canvas .canv-frame.canvas)
  82.  
  83.   ;; 
  84.   ;; Pack evrybody
  85.   ;;
  86.   (pack .title .nrframe .speed-frame .canv-frame .f :expand #t :fill "x")
  87.  
  88.   ;;
  89.   ;; key bindings
  90.   ;;
  91.   (bind "." "<KeyPress-r>"  (lambda () (DoHanoi [.nrframe.scale 'get] #t)))
  92.   (bind "." "<KeyPress-s>"  (lambda () (set! hanoi-stop #t)))
  93.   (bind "." "<KeyPress-q>"  (lambda () (exit 0)))
  94.   
  95.   ;; 
  96.   ;; Display tower
  97.   ;;
  98.   (DoHanoi num-rings #f)
  99. )
  100.  
  101. ;;
  102. ;; DoHanoi    
  103. ;;
  104. ;; Input:
  105. ;;    n    # of rings
  106. ;;
  107. ;; setup the canvas for displaying the Hanoi simulation
  108. ;; Call hanoi if run-it is true.
  109. ;;
  110. (define (DoHanoi n run-it)
  111.   (unless hanoi-running
  112.     (define ring-width         (+ width-min (* n width-incr)))
  113.     (define wm-width         (+ (* 3 ring-width) (* 4 12)))
  114.     (define wm-height           (+ (* ring-spacing n) fly-row (* 2 ring-height)))
  115.  
  116.  
  117.     (set! hanoi-stop      #f)
  118.     (set! hanoi-running     #t)
  119.     (set! base          (- wm-height 32))
  120.  
  121.     ;;
  122.     ;; cleanup from previous run
  123.     ;;
  124.     (do ((i 1 (+ i 1)))
  125.     ((> i previousRings))
  126.       (hanoi-canvas 'delete (cddr (vector-ref ring i))))
  127.     
  128.     ;;
  129.     ;; configure the canvas appropriately
  130.     ;;
  131.     (hanoi-canvas 'configure :width wm-width :height wm-height)
  132.     
  133.     ;;
  134.     ;; setup poles
  135.     ;;
  136.     (let loop ((i 0))
  137.       (vector-set! pole i (cons 0 (+ (* i (/ wm-width 3)) (/ ring-width 2) 8)))
  138.       (when (< i 2) (loop (+ 1 i))))
  139.     ;;
  140.     ;; setup rings
  141.     ;;
  142.     
  143.     (let loop ((i 0))
  144.       (let* ((colour (list-ref colours (modulo i 10)))
  145.          (w      (- ring-width (* i 12)))
  146.          (y         (- base (* i ring-spacing)))
  147.          (x      (- (cdr (vector-ref pole 0)) (/ w 2)))
  148.          (r      (- n i)))
  149.       
  150.     (vector-set! ring r 
  151.              (cons 0
  152.                (cons w
  153.                  (hanoi-canvas 'create 
  154.                           'oval x y (+ x w) (+ y ring-height)
  155.                           :fill colour 
  156.                           :outline colour
  157.                           :width 12)))))
  158.       (if (< i (- n 1)) (loop (+ i 1))))
  159.     
  160.     (vector-set! pole 0 (cons n (cdr (vector-ref pole 0))))
  161.     (set! previousRings n)
  162.  
  163.     (update)
  164.     (when run-it (Hanoi n 0 2 1))
  165.     (set! hanoi-running #f)))
  166. ;;
  167. ;; Hanoi : the guts of the algorithm
  168. ;;
  169. ;; Input:
  170. ;;    n    # of rings
  171. ;;    from    pole to move from
  172. ;;    to    pole to move to
  173. ;;    work    pole to aid in performing work
  174. ;;
  175. (define (Hanoi n from to work)
  176.   (when (and (> n 0) (not hanoi-stop))
  177.     (Hanoi (- n 1) from work to)
  178.     (unless  hanoi-stop (MoveRing n to))
  179.     (Hanoi (- n 1) work to from)))
  180.  
  181. ;;
  182. ;; MoveRing :    move a ring to a new pole
  183. ;;
  184. ;; Input:
  185. ;;    n    ring number
  186. ;;    to    destination pole
  187. ;;
  188. (define (MoveRing n to)
  189.   ;;
  190.   ;; ring(n,obj) can be queried as to its current position.
  191.   ;; Thus, we don't need to know which pole the ring is moving from.
  192.   ;;
  193.   (let* ((inc      0)
  194.      (tox     0)
  195.      (toy        0)
  196.      
  197.      (r        (cddr (vector-ref ring n)))
  198.      (coords  (hanoi-canvas 'coords r))
  199.      (x0       (list-ref coords 0))
  200.      (y0       (list-ref coords 1))
  201.      (x1       (list-ref coords 2))
  202.      (y1       (list-ref coords 3)))
  203.     
  204.     ;;
  205.     ;; move up to the "fly row"
  206.     ;;
  207.     (do ()
  208.     ((<= y0 fly-row))
  209.       (set! inc (if (> (- y0 fly-row) accel) accel (- y0 fly-row)))
  210.       (set! y0  (- y0 inc))
  211.       (set! y1  (- y1 inc))
  212.       (hanoi-canvas 'coords r x0 y0 x1 y1)
  213.       (update))
  214.  
  215.     ;;
  216.     ;; one less ring on this pole
  217.     ;;
  218.     (let ((tmp (car (vector-ref ring n))))
  219.       (set-car! (vector-ref pole tmp) (- (car (vector-ref pole tmp)) 1)))
  220.  
  221.     ;;
  222.     ;; determine target X position, based on destination pole, and fly ring
  223.     ;; over to new pole
  224.     ;;
  225.     (set! toX (- (cdr (vector-ref pole to)) 
  226.          (/ (cadr (vector-ref ring n)) 2)))
  227.  
  228.     (do ()
  229.     ((>= x0 toX))
  230.       (set! inc (if (> (- toX x0) accel) accel (- toX x0)))
  231.       (set! x0 (+ x0 inc))
  232.       (set! x1 (+ x1 inc))
  233.       (hanoi-canvas 'coords r x0 y0 x1 y1)
  234.       (update))
  235.  
  236.     (do ()
  237.     ((<= x0 toX))
  238.       (set! inc (if (> (- x0 toX) accel) accel (- x0 toX)))
  239.       (set! x0 (- x0 inc))
  240.       (set! x1 (- x1 inc))
  241.       (hanoi-canvas 'coords r x0 y0 x1 y1)
  242.       (update))
  243.  
  244.     ;;
  245.     ;; determine target Y position, based on ;; rings on destination pole.
  246.     ;;
  247.     (set! toY (- base (* (car (vector-ref pole to)) ring-spacing)))
  248.  
  249.     ;;
  250.     ;; float ring down
  251.     ;;
  252.     (do ()
  253.     ((>= y0 toY))
  254.       (set! inc (if (> (- toY y0) accel) accel (- toY y0)))
  255.       (set! y0 (+ y0 inc))
  256.       (set! y1 (+ y1 inc))
  257.       (hanoi-canvas 'coords r x0 y0 x1 y1)
  258.       (update))
  259.  
  260.     ;;
  261.     ;; increase destination pole usage
  262.     ;;
  263.     (set-car! (vector-ref pole to) (+ (car (vector-ref pole to)) 1))
  264.     (set-car! (vector-ref ring n) to)))
  265.  
  266.  
  267. (SetupHanoi)
  268.